//bind 后的方法普通调用，就是无论如何都不会再改变上下文 this 的调用
//bind 后的方法通过 new 实例化，其实就是实例化了原始函数，新实例的原型也指向了原始函数的原型
//已验证，逻辑和原生的 bind 函数一模一样；
Function.prototype.myBind = function(context = window){
    var fn = this;
    var args = Array.from(arguments).slice(1);
    var newFunc = function(){
        //组合两次的参数
        var newArgs = args.concat([...arguments]);
        if(this instanceof newFunc){
            //调用上下文是 newFunc 的实例
            //通过new 调用，绑定调用者为实例对象
            console.log("new 方式调用");
            fn.apply(this, newArgs);
        }else{
            fn.apply(context, newArgs);
            console.log("普通调用");
        }
    };
    //支持new 方式调用？-这个从哪里说起
    newFunc.prototype = Object.create(fn.prototype);
    return newFunc;
}

var me = {name:"Jack"};
var other = {name: "Jackson"};
function say(){
    console.log(`My name is ${this.name||'default'}`);
}
//say 函数绑定到 me 上
var meSay = say.myBind(me);
meSay();
var otherSay = say.myBind(other);
otherSay();

//bind 后的方法，普通调用，其内部this怎么都不会变的
//bind 后的方法，通过new生成一个对象，内部this应该使用生成的实例，执行类方法，传递的上下文为其实例，
//更改其 prototype 指向，所以得有 prototype
var obj = new meSay();


function A(name,age){
    this.name = name;
    this.age = age;
}
A.prototype.hello = function(){
    console.log(`hello ${name}`);
}
var obj = {name: "katy", age: 30};
var B = A.bind(obj);
var b = new B("win7", 28);
b.hello();
console.log(b.__proto__);